#pragma once
#include "epoller.hpp"
#include <memory>

class server{
    const static size_t NUM = 128;
public:
    server(uint16_t port)
        :_port(port)
        ,_sockptr(new Socket)
        ,_epollptr(new epoller)
    {}

    void init(){
        _sockptr->creSocket();
        _sockptr->Bind(_port);
        _sockptr->Listen();
    }

    void recver(int fd){
        char buffer[1024];
        int n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if(n > 0){
            buffer[n] = 0;
            cout << "get message: " << buffer << endl;
        }
        else if(n == 0){
            ls(Info, "fd: %d out", fd);
            _epollptr->epollCtl(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
        else{
            ls(Warning, "fd: %d error", fd);
            _epollptr->epollCtl(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
    }

    void dispatcher(int n, epoll_event events[]){
        for(int i = 0; i < n; i++){
            int fd = events[i].data.fd;
            uint32_t event = events[i].events;
            if(event & EPOLLIN){
                if(events[i].data.fd == _sockptr->getFD()){
                    uint16_t port;
                    string ip;
                    int fd = _sockptr->Accept(&ip, &port);
                    _epollptr->epollCtl(EPOLL_CTL_ADD, fd, EPOLLIN);
                    ls(Info, "get new link %s:%d", ip.c_str(), port);
                }
                else{
                    recver(fd);
                }
            }
            else{
                
            }
        }
    }

    void start(){
        epoll_event events[NUM];
        _epollptr->epollCtl(EPOLL_CTL_ADD, _sockptr->getFD(), EPOLLIN);
        while(true){
            int n = _epollptr->epollWait(events, NUM);
            if(n > 0){
                dispatcher(n, events);
            }
            else if(n == 0){
                ls(Info, "time out");
            }
        }
    }

    ~server(){
        _sockptr->Close();
    }

private:
    std::shared_ptr<Socket> _sockptr;
    std::shared_ptr<epoller> _epollptr;
    uint16_t _port;
};